//
//  XWScanViewController.swift
//  XWSurSpeed
//
//  Created by hopemobi-1 on 2024/8/8.
//

import UIKit
import AVFoundation

class XWScanViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {

    @IBOutlet weak var XWScanBackView: UIView!
    @IBOutlet weak var XWLineView: UIView!
    
    private var num = 0
    private var upOrdown = false
    private var timer:Timer!
//    private var cropLayer:CAShapeLayer!
//    private var path:CGMutablePath!
    
    private var device:AVCaptureDevice!
    private var input:AVCaptureDeviceInput!
    private var output:AVCaptureMetadataOutput!
    private var session:AVCaptureSession!
    private var preview:AVCaptureVideoPreviewLayer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        showUI()
        XWSetupCamera()
    }
    deinit{
        timer.invalidate()
        timer = nil
    }
    @IBAction func XWBackButtonClick(_ sender: UIButton) {
        timer.invalidate()
        dismiss(animated: true, completion: nil)
    }
    
    @IBAction func XWPhotoButtonClick(_ sender: UIButton) {
        if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
            let picker = UIImagePickerController()
            picker.delegate = self
            picker.sourceType = UIImagePickerController.SourceType.photoLibrary
            self.present(picker, animated: true)
        }else{
            let alert = UIAlertController(title: "tips", message: "Read album error", preferredStyle: .alert)
            alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: { UIAlertAction in
                
            }))
            self.present(alert, animated: true)
        }
    }
    
    @IBAction func XWFlashlightButtonClick(_ sender: UIButton) {
        if device.torchMode == AVCaptureDevice.TorchMode.off {
            do{
                try device.lockForConfiguration()
            }catch{
                return
            }
            device.torchMode = .on
            device.unlockForConfiguration()
        }else{
            do{
                try device.lockForConfiguration()
            }catch{
                return
            }
            device.torchMode = .off
            device.unlockForConfiguration()
        }
    }
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true) { [self] in
            let photoImage = info[.originalImage] as? UIImage
            XWGetQRCodeWithImage(photoImage!)
        }
    }
    
}
extension XWScanViewController:AVCaptureMetadataOutputObjectsDelegate{
    private func showUI(){
        timer = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(XWAnimation1), userInfo: nil, repeats: true)
//        cropLayer = CAShapeLayer()
//        path = CGMutablePath()
//        CGPathAddRect(path, nil, XWScanBackView.bounds)
//        CGPathAddRect(path, nil, XWScanBackView.bounds)
        
    }
    @objc private func XWAnimation1() {
        if upOrdown{
            num -= 1
            XWLineView.frame = CGRectMake(30, CGFloat(20+2*num), XWLineView.frame.size.width,  XWLineView.frame.size.height)
            if num == 0{
                upOrdown = false
            }
        }else{
            num += 1
            XWLineView.frame = CGRectMake(30, CGFloat(20+2*num), XWLineView.frame.size.width,  XWLineView.frame.size.height)
            if 2*num == 240 {
                upOrdown = true
            }
        }
    }
    private func XWSetupCamera(){
        device = AVCaptureDevice.default(for: .video)
        if device == nil{
            let alert = UIAlertController(title: "tips", message: "The device does not have a camera", preferredStyle: .alert)
            alert.addAction(UIAlertAction.init(title: "OK", style: .default, handler: { UIAlertAction in
                
            }))
            self.present(alert, animated: true)
            return
        }
        do{
            input = try AVCaptureDeviceInput.init(device: device)
        }catch{
            
        }
        output = AVCaptureMetadataOutput.init()
        output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        let top = 0.0
        let left = 0.0
        let width = XWScanBackView.frame.size.width
        let height = XWScanBackView.frame.size.height
        output.rectOfInterest = CGRectMake(top, left, height, width)
        session = AVCaptureSession.init()
        session.sessionPreset = .high
        if session.canAddInput(input){
            session.addInput(input)
        }
        if session.canAddOutput(output){
            session.addOutput(output)
        }
        output.metadataObjectTypes = [.qr]
        preview = AVCaptureVideoPreviewLayer.init(session: session)
        preview.videoGravity = .resizeAspectFill
        preview.frame = XWScanBackView.layer.bounds
        XWScanBackView.layer.insertSublayer(preview, at: 0)
        session.startRunning()
    }
    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        if metadataObjects.count > 0{
            session.stopRunning()
            let metadataObject:AVMetadataMachineReadableCodeObject = metadataObjects.first! as! AVMetadataMachineReadableCodeObject
            let vc = XWScanResultViewController()
            vc.XWResultString = metadataObject.stringValue! as String
            PresentViewController(vc)
            DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
                DispatchQueue.global(qos: .default).async {
                    self.session.startRunning()
                }
            }
            
        }else{
            let alert = UIAlertController.init(title: "tips", message: "No scan information", preferredStyle: .alert)
            alert.addAction(UIAlertAction.init(title: "ok", style: .default, handler: { UIAlertAction in
                
            }))
            self.present(alert, animated: true)
            return
        }
    }
}
extension XWScanViewController{
    private func XWGetQRCodeWithImage(_ photoImage:UIImage){
        let detector = CIDetector(ofType:CIDetectorTypeQRCode, context: nil,options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
        let features = detector?.features(in: CIImage(cgImage: photoImage.cgImage!))
        if features == nil || features!.count <= 0{
            self.showHint("The QR code is not recognized")
            return
        }
        for feature in features! {
            if let qrcode = feature as? CIQRCodeFeature{
                let vc = XWScanResultViewController()
                vc.XWResultString = qrcode.messageString!
                PresentViewController(vc)
            }
        }
    }
}
